package lumis.portal.sendmail.dao;

import lumis.portal.PortalException;
import lumis.portal.dao.DaoException;
import lumis.portal.sendmail.IBaseMail;
import lumis.portal.sendmail.IMailAttachment;
import lumis.portal.sendmail.IMailBody;
import lumis.portal.sendmail.IMailConfig;
import lumis.portal.sendmail.IMailDestination;
import lumis.portal.sendmail.IMailSendStatus;
import lumis.portal.sendmail.IMultipleMail;
import lumis.portal.sendmail.ISingleMail;
import lumis.util.ITransaction;

/**
 * The DAO for sendmail persistence information.
 * 
 * @version $Revision: 6251 $ $Date: 2007-03-27 10:49:29 -0300 (Tue, 27 Mar 2007) $
 * @since 4.0.4
 */
public interface ISendMailDao
{
	/**
	 * Factory method for creating a new blank mail instance.
	 * Use this method to obtain an instance of {@link ISingleMail},
	 * to fill it with the required data and use it in the
	 * other methods in this interface. 
	 * @return a new blank mail instance.
	 * @see #createMultipleMail()
	 * @see #createMailAttachment()
	 * @since 4.0.4
	 */
	public ISingleMail createSingleMail() throws PortalException;

	/**
	 * Returns a {@link ISingleMail} instance as the given mail addressed to the given destination.  
	 * @param mail the mail.
	 * @param destination the destination.
	 * @return the corresponding {@link ISingleMail} instance.
	 * @since 4.0.4
	 */
	public ISingleMail createSingleMail(IMultipleMail mail, IMailDestination destination);

	/**
	 * Factory method for creating a new blank mail instance.
	 * Use this method to obtain an instance of {@link IMultipleMail},
	 * to fill it with the required data and use it in the
	 * other methods in this interface. 
	 * @return a new blank mail instance.
	 * @see #createSingleMail()
	 * @see #createMailAttachment()
	 * @see #createMailDestination()
	 * @since 4.0.4
	 */
	public IMultipleMail createMultipleMail() throws PortalException;

	/**
	 * Factory method for creating a new mail destination instance.
	 * Use this method to obtain an instance of {@link IMailDestination},
	 * to fill it with the required data and use it in the
	 * other methods in this interface. 
	 * @return a new mail destination instance.
	 * @see #createMultipleMail()
	 * @see IMultipleMail#getDestinations()
	 * @since 4.0.4
	 */
	public IMailDestination createMailDestination();
	
	/**
	 * Factory method for creating a new mail attachment instance.
	 * Use this method to obtain an instance of {@link IMailAttachment},
	 * to fill it with the required data and use it in the
	 * other methods in this interface. 
	 * @return a new mail attachment instance.
	 * @see #createSingleMail()
	 * @see #createMultipleMail()
	 * @see IMailBody#getAttachments()
	 * @since 4.0.4
	 */
	public IMailAttachment createMailAttachment();

	/**
	 * Returns the IMailConfig containing the configurations for sending e-mails.
	 * @param transaction the transaction for persistence access.
	 * @return the IMailConfig, never null.
	 * @throws DaoException if it was not possible to obtain the IMailConfig.
	 * @see #setMailConfig(IMailConfig, ITransaction)
	 * @since 4.0.4
	 */
	public IMailConfig getMailConfig(ITransaction transaction) throws DaoException;

	/**
	 * Sets the IMailConfig containing the configurations for sending e-mails.
	 * @param mailConfig the IMailConfig.
	 * @param transaction the transaction for persistence access.
	 * @throws DaoException if it was not possible to set the IMailConfig.
	 * @see #getMailConfig(ITransaction)
	 * @since 4.0.4
	 */
	public void setMailConfig(IMailConfig mailConfig, ITransaction transaction) throws DaoException;
	
	/**
	 * Adds an mail to the send queue.
	 * @param mail the mail. This instance must have been created by {@link #createSingleMail()}.
	 * @param queueId the id of the queue where the mail will be added to. If null a new
	 * queue will be generated.
	 * @param transaction the transaction for persistence access.
	 * @throws DaoException if it was not possible to add the mail to the send queue.
	 * @see #addMailToSendQueue(IMultipleMail, String, ITransaction)
	 * @see #createMail()
	 * @see #createMailAttachment() 
	 * @since 4.0.4
	 */
	public void addMailToSendQueue(ISingleMail mail, String queueId, ITransaction transaction) throws DaoException; 

	/**
	 * Adds an mail to the send queue.
	 * @param mail the mail. This instance must have been created by {@link #createMultipleMail()}.
	 * @param queueId the id of the queue where the mail will be added to. If null a new
	 * queue will be generated.
	 * @param transaction the transaction for persistence access.
	 * @throws DaoException if it was not possible to add the mail to the send queue.
	 * @see #addMailToSendQueue(ISingleMail, String, ITransaction) 
	 * @see #createMail()
	 * @see #createMailAttachment() 
	 * @see #createMailDestination() 
	 * @since 4.0.4
	 */
	public void addMailToSendQueue(IMultipleMail mail, String queueId, ITransaction transaction) throws DaoException;

	/**
	 * Updates the mail send status as set in the given instance. The update is
	 * committed immediatelly.
	 * @param mailSendStatus the mail send status information.
	 * @since 4.0.4
	 */
	public void updateMailSendStatus(IMailSendStatus mailSendStatus) throws DaoException;

	/**
	 * Returns the next queued mail pending for sending, and marks its status
	 * as sending. Must also update the queue lock expiration date time.
	 * <p>
	 * This operation must be atomic and garantee that the same
	 * mail will not be returned many times, even if this method is called
	 * simultaneously by many threads in many servers in the cluster.
	 * @param queueId the id of the queue from where the mail will be taken.
	 * @return the mail or null if none was found.
	 * @since 4.0.4
	 */
	public IBaseMail fetchNextQueuedMail(String queueId) throws DaoException;

	/**
	 * Puts a mail back on its place in the queue to be available to another queue processing.
	 * It status will be changed to {@link IMailSendStatus#STATUS_SEND_PENDING}.
	 * @param mailId the mail id.
	 * @since 4.0.4
	 */
	public void unfetchMail(String mailId) throws DaoException;

	/**
	 * Returns for the next destination pending for sending for the given mail, and marks
	 * its status as sending. Must also update the corresponding queue lock expiration date time.
	 * <p>
	 * This operation must be atomic and garantee that the same
	 * destination will not be returned many times, even if this method is called
	 * simultaneously by many threads in many servers in the cluster.
	 * @param multipleMail the mail.
	 * @return the destination or null if none was found.
	 * @since 4.0.4
	 */
	public IMailDestination fetchNextPendingDestination(IMultipleMail multipleMail) throws DaoException;

	/**
	 * Locks the next queue mail available and returns its id. 
	 * <p>
	 * This operation must be atomic and garantee that a locked queue
	 * will not be returned, even if this method is called
	 * simultaneously by many threads in many servers in the cluster.
	 * @return the id of the locked queue, or null if there was no queue pending.
	 * @since 4.0.4
	 */
	public String lockNextQueue() throws DaoException;

	/**
	 * Returns a new generated queue id.
	 * @return a new generated queue id.
	 * @throws DaoException if the queue id could not be generated.
	 * @since 4.0.4
	 */
	public String generateNewQueueId() throws DaoException;

	/**
	 * Unlocks a mail queue.
	 * @param queueId the queue's id.
	 * @since 4.0.4
	 */
	public void unlockQueue(String queueId) throws DaoException;

	/**
	 * Deletes the whole mail structure, including the body, attachments, destinations.
	 * @param mailId the id of the mail to be deleted.
	 * @param transaction the transaction for persistence access.
	 * @throws DaoException if it was not possible to delete the mail.
	 * @since 4.0.4
	 */
	public void deleteMail(String mailId, ITransaction transaction) throws DaoException;

	/**
	 * Deletes the whole mail's body, including the body message and the attachments.
	 * @param mailId the id of the mail whose body is to be deleted. 
	 * @param transaction the transaction for persistence access.
	 * @throws DaoException if it was not possible to delete the mail.
	 * @since 4.0.4
	 */
	public void deleteMailBody(String mailId, ITransaction transaction) throws DaoException;
}